﻿using System;

namespace NodeJS.stream
{
    [NonScript]
    public interface IReadable
    {
        /// <summary>
        /// The read() method pulls some data out of the internal buffer and returns it. If there is no data available, then it will return null.
        /// </summary>
        /// <param name="size">If you pass in a size argument, then it will return that many bytes. If size bytes are not available, then it will return null.
        /// If you do not specify a size argument, then it will return all the data in the internal buffer.</param>
        /// <returns></returns>
        [ImportMember("read")]
        StringOrBuffer Read(int size = 0);

        /// <summary>
        /// Call this function to cause the stream to return strings of the specified encoding instead of Buffer objects.
        /// For example, if you do readable.setEncoding('utf8'), then the output data will be interpreted as UTF-8 data, and returned as strings.
        /// If you do readable.setEncoding('hex'), then the data will be encoded in hexadecimal string format.
        /// This properly handles multi-byte characters that would otherwise be potentially mangled if you simply pulled the Buffers directly and called buf.toString(encoding) on them. If you want to read the data as strings, always use this method.
        /// </summary>
        /// <param name="encoding"></param>
        void SetEncoding(Encoding encoding);

        /// <summary>
        /// This method will cause the readable stream to resume emitting data events.
        /// This method will switch the stream into flowing-mode. If you do not want to consume the data from a stream, but you do want to get to its end event, you can call readable.resume() to open the flow of data.
        /// </summary>
        void Resume();

        /// <summary>
        /// This method will cause a stream in flowing-mode to stop emitting data events. Any data that becomes available will remain in the internal buffer.
        /// This method is only relevant in flowing mode. When called on a non-flowing stream, it will switch into flowing mode, but remain paused.
        /// </summary>
        void Pause();

        /// <summary>
        /// This method pulls all the data out of a readable stream, and writes it to the supplied destination, automatically managing the flow so that the destination is not overwhelmed by a fast readable stream.
        /// </summary>
        /// <param name="destination">destination Writable Stream The destination for writing data</param>
        /// <param name="options">options Object Pipe options
        /// <para>end: Boolean End the writer when the reader ends. Default = true</para>
        /// </param>
        IWritable Pipe(IWritable destination, object options = null);

        /// <summary>
        /// This method will remove the hooks set up for a previous pipe() call.
        /// If the destination is not specified, then all pipes are removed.
        /// If the destination is specified, but no pipe is set up for it, then this is a no-op.
        /// </summary>
        /// <param name="destination"></param>
        void Unpipe(IWritable destination = null);

        /// <summary>
        /// This is useful in certain cases where a stream is being consumed by a parser, which needs to "un-consume" some data that it has optimistically pulled out of the source, so that the stream can be passed on to some other party.
        /// </summary>
        /// <param name="chunk"></param>
        void Unshift(StringOrBuffer chunk);
    }
}
